package com.base.library.utils;

import android.annotation.SuppressLint;
import android.os.Environment;
import android.provider.Settings;
import android.text.TextUtils;

import com.base.library.BaseApplication;
import com.base.library.permission.PermissionUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.Charset;
import java.util.UUID;

public class DeviceUtils {
    private static final String KEY_UDID = "KEY_UDID";
    private volatile static String udid;
    private static final String DEVICE_CACHE_FILE = "SLEEP.INSTALLATION.id";

    /**
     * Return the unique device id.
     * <pre>{1}{UUID(macAddress)}</pre>
     * <pre>{2}{UUID(androidId )}</pre>
     * <pre>{9}{UUID(random    )}</pre>
     *
     * @return the unique device id
     */
    public static String getUniqueDeviceId() {
        return getUniqueDeviceId("", true);
    }

    /**
     * Return the unique device id.
     * <pre>android 10 deprecated {prefix}{1}{UUID(macAddress)}</pre>
     * <pre>{prefix}{2}{UUID(androidId )}</pre>
     * <pre>{prefix}{9}{UUID(random    )}</pre>
     *
     * @param prefix The prefix of the unique device id.
     * @return the unique device id
     */
    public static String getUniqueDeviceId(String prefix) {
        return getUniqueDeviceId(prefix, true);
    }

    /**
     * Return the unique device id.
     * <pre>{1}{UUID(macAddress)}</pre>
     * <pre>{2}{UUID(androidId )}</pre>
     * <pre>{9}{UUID(random    )}</pre>
     *
     * @param useCache True to use cache, false otherwise.
     * @return the unique device id
     */
    public static String getUniqueDeviceId(boolean useCache) {
        return getUniqueDeviceId("", useCache);
    }

    /**
     * Return the unique device id.
     * <pre>android 10 deprecated {prefix}{1}{UUID(macAddress)}</pre>
     * <pre>{prefix}{2}{UUID(androidId )}</pre>
     * <pre>{prefix}{9}{UUID(random    )}</pre>
     *
     * @param prefix   The prefix of the unique device id.
     * @param useCache True to use cache, false otherwise.
     * @return the unique device id
     */
    public static String getUniqueDeviceId(String prefix, boolean useCache) {
        if (!useCache) {
            return getUniqueDeviceIdReal(prefix);
        }
        if (udid == null) {
            synchronized (DeviceUtils.class) {
                if (udid == null) {
                    final String id = SPUtils.getInstance().getString(KEY_UDID, null);
                    if (id != null) {
                        udid = id;
                        return udid;
                    }
                    return getUniqueDeviceIdReal(prefix);
                }
            }
        }
        return udid;
    }

    private static String readDeviceId(File cacheFile) {
        try {
            RandomAccessFile f = new RandomAccessFile(cacheFile, "r");
            byte[] bytes = new byte[(int) f.length()];
            f.readFully(bytes);
            f.close();
            return new String(bytes, Charset.defaultCharset());
        } catch (Throwable t) {
            t.printStackTrace();
        }
        return "";
    }

    private static void writeDeviceId(String deviceId, File cacheFile) throws IOException {
        if (cacheFile.exists()) {
            cacheFile.deleteOnExit();
        }
        FileOutputStream out = new FileOutputStream(cacheFile);
        out.write(deviceId.getBytes(Charset.defaultCharset()));
        out.close();
    }

    private static String getUniqueDeviceIdReal(String prefix) {
        try {
            final String androidId = getAndroidID();
            if (!TextUtils.isEmpty(androidId)) {
                return saveUdid(prefix + 2, androidId);
            }

        } catch (Exception ignore) {/**/}
        return saveUdid(prefix + 9, "");
    }

    /**
     * Return the android id of device.
     *
     * @return the android id of device
     */
    @SuppressLint("HardwareIds")
    public static String getAndroidID() {
        String id = Settings.Secure.getString(
                BaseApplication.context.getContentResolver(),
                Settings.Secure.ANDROID_ID
        );
        if ("9774d56d682e549c".equals(id)) return "";
        return id == null ? "" : id;
    }

    private static String saveUdid(String prefix, String id) {
        udid = getUdid(prefix, id);
        SPUtils.getInstance().put(KEY_UDID, udid);
        if (PermissionUtils.INSTANCE.hasStoragePermission()) {
            // 有存储权限 保存到文件中
            try {
                writeDeviceId(udid, getDeviceFile());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return udid;
    }

    private static String getUdid(String prefix, String id) {
        if (id.equals("")) {
            if (PermissionUtils.INSTANCE.hasStoragePermission()) {
                // 有存储权限 先获取一下文件是否存储
                String udid = readDeviceId(getDeviceFile());
                if (!TextUtils.isEmpty(udid)) {
                    return udid;
                }
            }
            // 拼接1个1 代表Android的唯一标识
            return "1" + prefix + UUID.randomUUID().toString().replace("-", "");
        }
        return "1" + prefix + UUID.nameUUIDFromBytes(id.getBytes()).toString().replace("-", "");
    }


    private static File getDeviceFile() {
        return new File(Environment.getExternalStorageDirectory(), DEVICE_CACHE_FILE);
    }
}
